User Guide For MacApp and PowerPlant Views Support
ODF Release 1
Table of Content
- Installation Instructions
- The New Form Sample
- The ViewTester Tool
- Adding MacApp or PowerPlant support to your part
- API Reference, Limitations and Known problems
- About the new ODF views
Be sure to read the Q & A ReadMe file first for a general overview of this package.
Installation Instructions (Common to MacApp and PowerPlant)
This add-on works with the ODF 1 release. The instructions refer to CodeWarrior projects but MPW users should be able to adapt them to their environment.
Copy the new files and examples to your ODF kit
• Move the folder Other View Systems inside your ODF folder (at the same level as Found, OS & Framewrk)
• Move the examples ViewTester and Form (MA/PP) inside your ODFDev folder, at the same level as other examples. (Form (MA/PP) is a modified version of the original Form sample which adds support for MacApp and PowerPlant, it won't replace your existing Form folder.)
Try the new Form and ViewTester parts (PPC versions)
The Form and ViewTester parts are already built in their CWPPCDebug folders. Copy an alias to these parts into your editors folder. (If you are running on 68K you'll need to rebuild these parts, see the section on Form and ViewTester below.)
IMPORTANT: you must remove the current Form part (or alias) from your Editor folder in order to be sure that the new part will be used instead. You may also need to reboot your Mac. The stationery format hasn't changed so you can use the same ODFForm stationery.
Form
• Open your ODFForm R1 stationery. You should see the same Form part running, the UI of this version was build with PowerPlant Constructor but it's hard to tell! To be sure you're running the new version of Form see the new "Reload PPob Views" command in the Form menu (if you don't see it OpenDoc is still loading your old Form part, did you reboot your Mac?).
• Without quitting the part open the :CWPPCDebug:ODFForm.π project and double-click on ODFForm.ppob in the Resources, it will open it with Constructor. Open the FormView window, try moving something around or adding a new view somewhere, then save the file.
• Switch back to the Form part and do "Reload PPob Views": this opens a file dialog the first time you use it. Select the ODFForm.ppob file you just modified in Constructor (inside the :Form:Sources folder). The frame is modified with your changes and moved back to its original location and size!
• Notice that views which cannot be converted by ODF are displayed as red rectangles containing the class id in the top left corner.
See the section "The New Form Sample" below for more information.
ViewTester
This is a new part, more a tool than a standard ODF sample. Create a stationery document and launch it. The first frame provides basic instructions.
You can open any MacApp or PowerPlant resource file and test the conversion of View and PPob resources. A good example is to try the applications Ad Lib and Constructor themselves because they contain many different windows.
Unlike Form, ViewTester is built to support MacApp and PowerPlant simultaneously so you shouldn't have to rebuild it.
Make patches to ODF to enable the "Reload Views" feature
In order to make the "Reload Views" command work, and to be able to rebuild Form or ViewTester, 2 patches are necessary in the ODF static libraries, one in the Framework library and one in the Foundation library. (These will be fixed in ODF 2. If you don't want to make these patches you can still make your part load MacApp or PowerPlant views, but you won't be able to add the "Reload Views" command like in Form.)
After making these changes use the ODF Builder tool to rebuild the Framework and Foundation libraries, or open the projects ODFFoundation.π and ODFFramewrk.π directly.
Change to ODF:Framewrk:FWPart:Sources:FWFrame.cpp/.h
Add the following DeleteAndResetViews method to the FW_CFrame class:
• The first patch (DeleteAndResetViews) is necessary to leave a frame in a clean state after deleting all its subviews.
Since the "Reload Views" command uses this method you won't be able to link if you forget to patch the framework library.
• The second patch is more subtle. It is a fix to a bug that occurs only when deleting a FW_CRadioCluster view that was created from a PowerPlant resource, because of the order of creation between Clusters and Radio buttons (i.e. we were just lucky the bug didn't occur with ODFRC views!)
The New Form Sample
Features
The folder Form (MA/PP) contains a modified version of the Form sample.
• The part can be built in 3 different ways, depending on the flags set in Defines.k:
#define FW_ODFRC_VIEWS 0
#define FW_MACAPP_VIEWS 0
#define FW_PPOB_VIEWS 1
• When FW_ODFRC_VIEWS is set to 1 the part uses the ODF resources defined in Views.fr. In this version we've simplified the code of CFormView by making it derive from the new FW_CPictSView class.
• When FW_MACAPP_VIEWS is set to 1 the part uses the MacApp resources defined in ODFForm.rsrc and links the code from the 2 FWMAxxxx.cpp source files which provide MacApp support.
• When FW_PPOB_VIEWS is set to 1 the part uses the PPob resources defined in ODFForm.ppob and links the code from the 2 FWPPobxx.cpp source files which provide PowerPlant support (PPob is the resource type for views in PowerPlant).
• The debug version adds a menu command "Reload MacApp Views" or "Reload PPob Views" to the Form menu. This command allows you to update the Form frame dynamically after making a change in ODFForm.rsrc (with Ad Lib) or ODFForm.ppob (with Constructor).
WARNING: it's dangerous to load any other resource files than these two, because Form's code works only with these known views. Also, it is dangerous to delete views or change their ids. The Reload command is safe only after changing some view attributes or adding new views that don't interfere with the code.
The current "Reload" implementation brings up a file dialog the first time around to pick a resource file. The same resource file is used in subsequent Reload actions. The ViewTester part uses for a more advanced interface.
• Most views used in Form are standard control, edit-text and list-box views which map directly to the corresponding classes in MacApp and PowerPlant. However 3 instances of custom classes show you how to extend this MacApp and PowerPlant support:
- CFormView (in FormView.cpp) derives from FW_CPictSView. It uses a custom 'Form' class in Constructor and "TForm" class in Ad Lib.
- CPwdEditView (in Dialog.cpp) derives from FW_CEditView. It uses a custom 'PwEd' class in Constructor and "TPwdEdit" class in Ad Lib.
- CScrollEdit (in ScrollEd.cpp) derives from FW_CEditView. It uses a custom 'ScEd' class in Constructor and the standard "TEView" class in Ad Lib.
Support for Custom Classes
Let's take the example of the CFormView class in FormView.cpp. This is a picture view (it derives from FW_CPictSView) which needs an additional persistent field to hold the id of a second picture (fPicture2).
If you open ODFForm.ppob with Constructor you'll see in the Display Classes window that it contains a custom class "CFormView", with the id 'Form', based on the PowerPlant class "LPicture". Then if you open the FormFrame PPob 1024 and double-click on the background picture it brings up the CFormView editor, which is the LPicture editor augmented with a field for the 2nd picture resource ID.
The first step in the code is to register the new class in CFormPart::Initialize:
// Important: all superview classes must call PostCreateODFView before returning
PostCreateODFView(ev, view);
delete this; // we don't need you anymore...
}
CreateODFView is called automatically by the PPob Reader for each object found in the stream. It's simple to create the CFormView instance at that time, now that all CPPobFormView fields are ready to be converted to ODF.
Notice that all superview classes must call PostCreateODFView. This is to ensure that ODF will create the frame's content view at the first scrolling view it finds (which is the case for CFormView here).
Finally the "PPob" object must be deleted after the conversion to ODF.
Additional Notes & Known Bugs
• We have provided only the CWPPCDebug project. To build CodeWarrior release or 68K versions you can start from the original Form projects and add the new files. To build MPW versions you can also follow the example of the original Form sample.
• The "Reload Views" command will be modified in the next release so that it can find the <part>.rsrc or <part>.ppob resource file by default in the Sources folder where it generally resides (a bug in the ODF 1 library file subsystem prevented us from adding this feature.)
• The Linker warnings are turned off to avoid messages about duplicate MENU and PICT resources in ODFForm.rsrc and ODFForm.ppob (each file must contain a copy of these additional Mac resources in case they are used separately).
• Using #define flags in order to switch between view systems was done for the sake of this example and doesn't reflect normal cases where only one kind of view is used.
• Bug: using the "Reload Views" command when Form is embedded in another part doesn't restore the scroll bars properly. The work-around is to resize the frame a little bit.
The ViewTester tool
This new part has two main purposes: to allow you to quickly test the conversion of existing MacApp or PowerPlant views to ODF, or to see your part's UI while building it with Ad Lib or Constructor. It is built with the same MacApp and PPob "reader" modules that Form uses but works as a generic part without any knowledge of the UI being loaded (i.e. the converted views are just displayed as is and not wired to any code.)
Using ViewTester
A PPC version of ViewTester is already built and supports both MacApp and PowerPlant simultaneously so you should not have to rebuild it unless you are running on 68K or made some modifications.
After putting an alias to ViewTester in your Editors folder, and creating stationery, launch the part. It opens with a starting frame containing some instructions. Once you open a MacApp or PowerPlant resource file ViewTester will display the converted views in a separate "test frame" which takes the position and size of the window.
The MacApp and PowerPlant menus are similar:
• TheReload Views command is enabled only after you have selected a resource file. It allows you to reload the same PPob or View resource from the current file, for instance after you modified it in Ad Lib or Constructor.
• The Use New Resource command is enabled only after you have selected a resource file. It allows you to switch to another PPob or View resource in the current file with the same dialog box that appears when you open a new resource file.
• The Open New File command is always enabled. It allows you to open any resource file containing MacApp or PowerPlant resources. The file dialog lets you select files of types rsrc, RSRC, aLib and APPL for MacApp, and types rsrc, RSRC, and APPL for PowerPlant. (i.e. you can even select existing applications and read their view resources! try it with Ad Lib and Constructor themselves...) Once the file is selected a separate dialog box lets you select the view by name or by id. Its popup menu contains only the named resources.
MACAPP WARNING: before opening an existing MacApp file be sure that it was generated by Ad Lib. MacApp resources that were built from a .r file (with Rez) don't contain as much information and won't be converted as easily. The solution is to open them first with Ad Lib and save them back. Try this for instance on the MacApp DemoDialog example, DemoDialogs_d.π.rsrc.
POWERPLANT WARNING: when creating a new Constructor project file and saving it without closing the project it seems that Constructor doesn't save things correctly, so if you try to open it in ViewTester you won't see the new resources. Make sure you close your new project file before using it in ViewTester.
The other features of ViewTester are the following:
• The test frame can always be resized, even if no grow box was created in the bottom right corner. This allows to test the binding flags of views. Also the frame's background is purple to make the location of views more explicit.
• The Error log field gives information on what went wrong during the view conversion. ViewTester beeps at the same time to remind you to check the Error log.
• Debugger warnings are on by default, so in case of errors you will first get warnings in your debug console (Macsbug or the CodeWarrior debugger). Do not exit after a warning, ViewTester will recover and show you the partially built frame. However if you get a debugger break without the label "warning" it's a more serious error which should be tracked down or reported.
• The "Turn Off Warnings" check box can be selected to turn off the debug console.
• ViewTester keeps track of both the current MacApp file and the current PowerPlant file. The file name is displayed in the window title of the view selection dialog and of the test frame.
• Since ViewTester is a generic part it cannot convert your custom classes. They will be displayed as unknown views like other unregistered views. Try this for instance on the ODFForm.rsrc and ODFForm.ppob files.
• When loading PowerPlant views you may get the following message: "Some pink (unregistered) views are simple subclasses of registered views. Hold the Shift key down and do 'Reload Views' to use the known views"
This means that ODF found 1 or more unknown view objects whose parent class is registered. Doing "Reload Views" with shift down sets an internal "UseClassAlias" flag and tells ODF to display the parent class instead. This way you can see better what kind of views were not registered.
As an example open the file ODFForm.ppob and pick the view FormView: you should get this message in the error log and see two unknown views, 'Form' and 'ScEd'. Then do "Reload Views" with shift down, 'ScEd' is replaced by an edit view, 'Form' is still left unknown because it's not a simple subclass if LPicture. (It adds a data field, i.e. uses a CPPb resource instead of a simple alias in the stream.)
Rebuilding ViewTester
You need to rebuild ViewTester in 2 cases:
• to build a 68K version: use the project inside :ViewTester:CW68KDebug. (We don't recommend using a "release" version of ViewTester, we didn't provide the release projects on purpose!)
• to incorporate changes you made to the MacApp or PPob reader module. You may want to add support for more view classes, including custom classes used in your part(s). Follow the same instructions given to support custom classes in your part but move the code to the FWMAxxx or FWPPobxx files.
Additional Notes & Known Bugs
• ViewTester shows all views, even if they overlap or have an "invisible" flag set.
• The new file dialog lets you open any resource file so it is possible to pick a non-MacApp or non-PowerPlant file. In that case you won't be able to select any View or PPob resource, and you'll get the error "View not found".
• If you close the starting frame but keep the test frame open the part is still running. You cannot bring the starting frame back but you can still switch to other views or another resource file. However you won't get any error log, just the Debugger breaks if you left the warnings option on.
• When embedding ViewTester in another part only the starting frame (its main presentation) is embedded. The test frame always opens in a separate window.
• Bug: because the "Turn Off Warnings" check box is handled at the part level it won't be updated correctly in case of multiple frames of the main presentation.
• Bug: MacApp & Powerplant menus disappear when you close the test frame. Click on the main frame to get them back.
For more information on the rules and limitations of the view conversion see the separate release notes "MacApp Views.doc" and "PowerPlant Views.doc".
Adding MacApp or PowerPlant support to your part
We assume here that you have already started to build your part's UI with Ad Lib or Constructor, or that you are re-using existing view resources, and that you have checked the ODF conversion with the ViewTester tool. This section explains how to put things together in your project and modify your source code in order to use these views. All code samples are taken from Form's source files.
Follow these steps:
1) Add the view resource file to your project
The convention is to name the file <part_name>.rsrc for Ad Lib and <part_name>.ppob for Constructor. Put it in the group Resources, next to the .r files.
2) Add necessary support files to your project
Unlike Form.π which can be compiled to use either MacApp or PowerPlant views, your project will generally use only one of them. For instance, to use PowerPlant views, you only need to add the 2 PPob support files and the new ODF view files. (If you are not going to use a Picture view you don't need FWPictSv.cpp and FWAPictV.cpp. FWUnknow.cpp is always needed because the "unknown" view class is referenced by the MacApp and PPob reader source.)
3) Add the class registrations in your part's Initialize() method
For PowerPlant:
// Register the standard PP classes
FW_CPPobReader::RegisterAllPPClasses();
For MacApp:
// Register the standard MacApp classes
FW_CMacAppReader::RegisterAllMacAppClasses();
IMPORTANT: Custom classes require separate registration as described in the section on Form above.
4) Do NOT pass a frame view id in your part's NewFrame() method
Check that your part's NewFrame method is not passing a view id as the last argument to the frame's constructor. Doing so would make ODF try to load the native ODFRC resource with that id instead of calling the frame's CreateSubViews method which is what we need.
The 3rd parameter is "this" in order to make the frame the root view of the views being loaded. (it could be another superview if one already existed.)
The 4th parameter is usually"this" too in order to make the frame the receiver for all controls being loaded. This avoids having to make an extra call to FW_CPPobReader::LinkReceiverToControls after loading the views. Use a NULL argument if you don't want to link controls automatically. You can also call LinkReceiverToControls afterward and pass a different receiver. (In the case of MacApp where LinkReceiverToControls doesn't exist you would need to connect each control individually to its receiver, after finding them by view id.)
The last parameter should be the kPartOnly constant for a finished part. This ensures that the MacApp or PPob reader will only look for view resources in the part's shared library and not try to open another resource file. (See the ViewTester part for the use of other constants.)
CreateSubViewsFromXXXResource catches exceptions and returns an ODF error code. Once your part is tested there should not be any surprises! See the code of the ViewTester part for more info on error handling.
6) Add code to support custom classes, including your frame's content view.
When your frame uses a separate content view (like CFormView in Form) or when it needs to use other custom view classes (like CScrollEdit in Form) you must define the mapping between these ODF classes and the MacApp or PowerPlant classes used in the part's UI. Basically you need a little extra code to extend the MacApp or PPob reader module in order to have the right conversion done at load time. See the discussion on custom views in the section on Form above.
IMPORTANT: Remember that an ODF frame can use only one scrolling view for its content (the content view). If your UI doesn't contain any scrollers the frame remains the content view. Otherwise the first scrolling view is converted into the content view and additional scrollers will generate a warning and be ignored by ODF. However there are ways to handle standard scrolling views such as text-edit and list boxes. See how this is done in Form.
Note: you may not have to implement all the custom class support right away. Views which are not registered will be created as instances of FW_CUnknownView and displayed as red rectangles with the class id in the top left corner. Unless the code is really dependent on the existence of particular views the part can run with a few "holes" in its interface and functionality!
7) Add the "Reload Views" menu command if necessary
Having a "Reload Views" command is useful in debug mode while you are developing your part and adjusting its interface. See how this is implemented in Form.
The ReloadViews method takes the same arguments as CreateSubViewsFromXXXResource:
The last argument should be kCurrentResFile. The effect is to open a file dialog the first time this is called and let the user select a resource file. Subsequent calls reuse the same resource file.
WARNING: ReloadViews starts by calling FW_CFrame::DeleteAndResetViews to delete all the frame's subviews and then it calls CreateSubViewsFromXXXResource to load the views again. In general your part shouldn't be affected by this operation, i.e. it should be the same as if the views were created for the first time when the frame was created. However the destruction of views may have side effects in your code that you will have to deal with...
8) Build and test
The main sources of problems will be one of the following:
• Link error: cannot find ResetViews.
-> you forgot to patch the framework library as explained in the installation instructions.
• Your part launches but the frame is empty.
-> Check that you used the right 'PPob' or 'View' id in CreateSubViewsFromXXXResource.
-> Check the error code returned.
• Your part launches but you get assertions during the views loading.
-> See the separate release notes "MacApp Views.doc" or "PowerPlant Views.doc" for more information on current limitations and issues.
-> The final version of your part should be built in Release mode to remove all debugger warnings.
• Your part launches but crashes when the frame is created.
-> Most certainly something wasn't converted correctly and the part tried to use an invalid view.
1) Load the same resource file with the ViewTester and check the returned errors.
(The ViewTester will show your custom views as "unknown")
2) If all the views are present the problem may come from the code which handles custom views.
Step with a debugger to verify that all fields are read correctly.
-> if you can't find the cause of the crash please report it to the ODF-Interest list, if possible with a test case.
Additional Notes
• Having more than one presentation use MacApp or PowerPlant views is the process. Each presentation's frame must load the views with the correct id.
• It is also possible to use more than one view resource kind at a time. ViewTester for instance uses ODF views for its main presentation and loads either MacApp or PowerPlant views in its test frame.
• In this release it is not possible to save the converted views back into ODF format in order to avoid linking with the MacApp or PowerPlant reader code. This will be added for ODF 2.
• PICT resources (for Picture views) and MENU resources (for popup menus) must be present in the current resource file.
API Reference, Limitations and Known problems
See the separate release notes "MacApp Views.doc" and "PowerPlant Views.doc". (These files are accessible from the Form.π and ViewTester.π projects.)
About the new ODF views
This package introduces 2 new view classes which will become part of the Framework library in ODF 2. Right now they can be linked as external source files in your project.
Picture view: FW_CPictSView
The implementation is in FWPictSv.cpp and FWAPictV.cpp (separate file to allow dead-stripping). FW_CPictSView is a subclass of FW_CSuperView which displays a Mac picture based on its PICT id.
• FW_CPictSView is used in particular in the new Form example as the parent class of CFormView.
• PowerPlant's LPicture and MacApp's TPicture classes are mapped to FW_CPictSView.
• The PICT resource must be present in the "current" resource file in order to be displayed, otherwise ODF displays a pink rectangle with an error message. (For instance if your part is linked with a resource file containing the right PICT resource but you select another resource file to reload the views you won't see the picture.)
• FW_CPictSView derives from FW_CSuperView instead of FW_CView so that it can scroll and be a content view. If you don't pass any extent to the constructor it will use the picture's size by default and thus will avoid scaling.
• FW_CPictSView comes with its ODF resource type FW_RPictSView defined in a new version of FWViews.fr.
IMPORTANT: in order to use an ODF Picture view resource in your Views.fr, like Form does, you must make sure that you use the new version of FWViews.fr. You can either copy FWViews.fr over the old version in :ODF:Framewrk:FWViews:Include: or you can leave it there and add the right access path to your project before the access path to :ODF:Framewrk:
Unknown view: FW_CUnknownView
This class allows you to display any MacApp or PowerPlant view which is not registered in a generic fashion: a red rectangle shows the space taken by the view and its class id identifies the missing class.
FW_CUnknownView derives from FW_CSuperView instead of FW_CView so that it can scroll and be a content view.